#include "lib_ArrayList.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

static	size_t
lib_ArrayList_size(const lib_s_ArrayList*	arrayList);

static	void
lib_ArrayList_moveToFirst(lib_s_ArrayList*	arrayList);

static	lib_t_boolean	
lib_ArrayList_hasNext(const lib_s_ArrayList*	arrayList);

static	void*
lib_ArrayList_getNext(lib_s_ArrayList*	arrayList);

static	lib_t_boolean
lib_ArrayList_removeItem(lib_s_ArrayList*	arrayList);

static	void*	
lib_ArrayList_get(const	lib_s_ArrayList*	arrayList,	size_t	position);

static	lib_t_boolean	
lib_ArrayList_remove(lib_s_ArrayList*	arrayList,	size_t	position);

static	void	
lib_ArrayList_clear(lib_s_ArrayList*	arrayList);

static	lib_t_boolean	
lib_ArrayList_add(lib_s_ArrayList*	arrayList,	void*	item);

static	lib_t_boolean 
lib_ArrayList_addItem(lib_s_ArrayList*	arrayList,	void*	item,	size_t	position);

lib_s_ArrayList*	lib_ArrayList_init(size_t	size)
{
	lib_s_ArrayList*	arrayList =	malloc(sizeof(lib_s_ArrayList));
	if(arrayList	==	NULL)
	{
		return	NULL;
	}
	memset(arrayList,	0,	sizeof(sizeof(arrayList)));
	int	ast_size	=	0;
	if(size	==	0)
	{
		ast_size	=	LIB_ARRAYLIST_DEFAULT;
	}
	else
	{
		ast_size	=	size;
	}

	arrayList->st_mallocSize	=	ast_size;
	arrayList->st_length	=	0;
	arrayList->st_index	=	0;
	arrayList->v_items	=	malloc(ast_size	*	sizeof(void*));
	if(arrayList->v_items	==	NULL)
	{
		return	NULL;
	}
	arrayList->size	=	lib_ArrayList_size;
	arrayList->add	=	lib_ArrayList_add;
	arrayList->moveToFirst	=	lib_ArrayList_moveToFirst;
	arrayList->addItem	=	lib_ArrayList_addItem;
	arrayList->clear	=	lib_ArrayList_clear;
	arrayList->hasNext	=	lib_ArrayList_hasNext;
	arrayList->getNext	=	lib_ArrayList_getNext;
	arrayList->removeItem	=	lib_ArrayList_removeItem;
	arrayList->get	=	lib_ArrayList_get;
	arrayList->remove	=	lib_ArrayList_remove;
	return	arrayList;
}

static	size_t
lib_ArrayList_size(const lib_s_ArrayList*	arrayList)
{
	if(arrayList	!=	NULL)
	{
		int	a_hope	=	0;
		a_hope	=	arrayList->st_length;
		if(a_hope	<	0)
		{
			return	0;
		}
		else
		{
			return	a_hope;
		}
	}
	return	0;
}

static	void
lib_ArrayList_moveToFirst(lib_s_ArrayList*	arrayList)
{
	if(arrayList	==	NULL)
	{
		return;
	}
	arrayList->st_index	=	0;
}

static	lib_t_boolean	
lib_ArrayList_hasNext(const lib_s_ArrayList*	arrayList)
{
	if(arrayList	!=	NULL)
	{
		if(arrayList->st_index	<	arrayList->st_length)
		{
			return	lib_gb_true;
		}
	}
	return lib_gb_false;
}

static	void*
lib_ArrayList_getNext(lib_s_ArrayList*	arrayList)
{
	if(arrayList	!=	NULL)
	{
		if(lib_ArrayList_hasNext(arrayList))
		{
			void*	a_hope	=	*(arrayList->v_items	+	arrayList->st_index);
			arrayList->st_index++;
			return	a_hope;
		}
	}
	return	NULL;
}

static	lib_t_boolean
lib_ArrayList_removeItem(lib_s_ArrayList*	arrayList)
{
	if(arrayList	!=	NULL)
	{
		lib_ArrayList_remove(arrayList,	arrayList->st_index);
		return	lib_gb_true;
	}
	return	lib_gb_false;
}

static	void*	
lib_ArrayList_get(const	lib_s_ArrayList*	arrayList,	size_t	position)
{
	if(arrayList	!=	NULL)
	{
		if(position	<	arrayList->st_length)
		{
			return *(arrayList->v_items +	position);
		}
		
	}
	return NULL;
}

static	lib_t_boolean	
lib_ArrayList_remove(lib_s_ArrayList*	arrayList,	size_t	position)
{
	if(arrayList	!=	NULL	||	position	<=	arrayList->st_length)
	{
		memcpy((arrayList->v_items	+	position),	(arrayList->v_items	+	position	+	1),	sizeof(void*)	*	(arrayList->st_length	-	position	-	1));
		arrayList->st_length--;
	}
	return	lib_gb_false;
}

static	void	
lib_ArrayList_clear(lib_s_ArrayList*	arrayList)
{
	if(arrayList	==	NULL)
	{
		return;
	}
	int	a_i;
	int	a_size	=	arrayList->st_length;
	for(a_i	=	0;	a_i	<	a_size;	a_i++)
	{
		free(*(arrayList->v_items	+	a_i));
	}
	free(arrayList->v_items);
}

static	size_t
lib_ArrayList_newCapacity(size_t	size)
{
	size_t	a_increase	=	size	>>	2;
	return	a_increase	+	size;
}

static	lib_t_boolean	
lib_ArrayList_add(lib_s_ArrayList*	arrayList,	void*	item)
{
	if(item	!=	NULL	||	arrayList	!=	NULL)
	{
		lib_ArrayList_addItem(arrayList,	item,	arrayList->st_length);
	}
	return	lib_gb_false;
}

static	lib_t_boolean 
lib_ArrayList_addItem(lib_s_ArrayList*	arrayList,	void*	item,	size_t	position)
{
	if(item	!=	NULL	||	arrayList	!=	NULL)
	{
		int	a_malloc	=	arrayList->st_mallocSize;
		if(position		>=	a_malloc)
		{
			size_t	a_newCap	=	lib_ArrayList_newCapacity(a_malloc);
			arrayList->v_items	=	realloc(arrayList->v_items,	a_newCap	*	sizeof(void*));
			if(arrayList->v_items)
			{
				assert(lib_gb_false);
			}
			arrayList->st_mallocSize	=	a_newCap;
			
		}

		*(arrayList->v_items	+	position)	=	item;
		arrayList->st_length++;
		return	lib_gb_true;
	}
	return lib_gb_false;
}

